/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package course.ya.doc.from.code.model.statements;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Admin
 */
public class StateFactory implements IStatementFactory {

    private static IStatementFactory instance;
    private Pattern pattern;
    private Matcher matcher;

    private StateFactory() {
    }

    public static IStatementFactory getInstance() {
        if (instance == null) {
            instance = new StateFactory();
        }
        return instance;
    }

    private boolean isIfStatement(String statement) {
        this.pattern = Pattern.compile("^if\\s*[(].+[)]$", Pattern.DOTALL);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isElseIfStatement(String statement) {
        this.pattern = Pattern.compile("^else if\\s[(](.*)[)]$");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isElse(String statement) {
        return "else".equals(statement);
    }

    private boolean isBreakStatement(String statement) {
        return "break".equals(statement);
    }

    private boolean isWhile(String statement) {
        this.pattern = Pattern.compile("^while\\s*[(].+[)]$", Pattern.DOTALL);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isDoWhile(String statement) {
        this.pattern = Pattern.compile("^do$");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isFor(String statement) {
        this.pattern = Pattern.compile("^for\\s*[(]  (.*;.*;.* | \\s*[A-z]\\w*\\s[A-z]\\w*\\s*[:].+) [)]$", Pattern.COMMENTS);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isSwitch(String statement) {
        this.pattern = Pattern.compile("^switch\\s+[(]\\w+[)]$");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isDeclarationFieldStatement(String statement) {
        this.pattern = Pattern.compile("^(public\\s+|private\\s+|protected\\s+)?"
                + "(?:static\\s+)?(?:final\\s+)?"
                + "([A-z]\\w*)"
                + "\\s?(<.+>)?  (\\[\\d*\\])? (\\s+[A-z]\\w*\\s*)"
                + "("
                + "(=\\s*"
                + "("
                + "(['\"]) .* (\\9) $|"
                + "new\\s+([A-z]\\w*)\\s?(<.+>)?(\\[\\d*\\])?  (\\s?[(].*[)])? $|"
                + "([A-z]\\w*([.][A-z]\\w*)*)  (\\s?[(].*[)])?$|"
                + "[-]?\\d+$"
                + ")"
                + ") | $"
                + ") $", Pattern.COMMENTS | Pattern.DOTALL);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isReturn(String statement) {
        this.pattern = Pattern.compile("^return\\s+.+$");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isComment(String statement) {
        this.pattern = Pattern.compile("//(.*)");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isExpression(String statement) {
        this.pattern = Pattern.compile("^[A-z_]\\w*([.]?[A-z_]\\w*)*     \\s*[!+-/*]?[=]\\s*  (new\\s+)? ([\\\"'])? \n"
                + "            (?:(?<=[\\\"']) \n"
                + "            .*(\\3) | \\w\\w* \n"
                + "            ([.(]? \n"
                + "            (?:(?<=[.]) [_A-z]\\w* | .*[)] ))*)", Pattern.COMMENTS);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isCallMethodStatement(String statement) {
        this.pattern = Pattern.compile("^([_A-z]\\w*)"
                + "([.(]"
                + "(?:(?<=[.])"
                + "   ([_A-z]\\w*) | .*[)]))+$", Pattern.COMMENTS);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isPackageStatement(String statement) {
        this.pattern = Pattern.compile("^package\\s+(\\w+[.]?)+\\w$", Pattern.COMMENTS);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isDeclarationMethodStatement(String statement) {
        this.pattern = Pattern.compile("^(public|private|protected)?\\s*([_A-z]\\w*)"
            + "(<.+>)?  \\s+([_A-z]\\w*\\s*)[(]((?s).*)[)]"
                + "(\\s+(throws)?\\s+(\\w+\\s*,?\\s*\\w*)*)*$", Pattern.COMMENTS | Pattern.DOTALL);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isIncDecStatement(String statement) {
        this.pattern = Pattern.compile("^[A-z]\\w*\\s?([+]{2}|--)$");
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    private boolean isThrowStatement(String statement) {
        this.pattern = Pattern.compile("^throw\\b\\s?.+$", Pattern.DOTALL);
        matcher = pattern.matcher(statement);
        return matcher.find();
    }

    @Override
    public AStatement getStatement(String statement) {
        statement = statement.trim();

        if (isElseIfStatement(statement)) {
            return new ElsIfStatement(statement);
        }
        else if (isIfStatement(statement)) {
            return new IfStatement(statement);
        }
        else if (isElse(statement)) {
            return new ElseStatement();
        }
        else if (isPackageStatement(statement)) {
            return new PackageStatement(statement);
        }
        else if (isDoWhile(statement)) {
            return new DoWhileStatement(statement);
        }
        else if (isWhile(statement)) {
            return new WhileStatement(statement);
        }
        else if (isSwitch(statement)) {
            return new SwitchStatement(statement);
        }
        else if (isThrowStatement(statement)) {
            return new ThrowStatement(statement);
        }
        else if (isFor(statement)) {
            return new ForStatement(statement);
        }
        else if (isReturn(statement)) {
            return new ReturnStatement(statement);
        }
        else if (isDeclarationFieldStatement(statement)) {
            return new FieldDeclarationStatement(statement);
        }
        else if (isDeclarationMethodStatement(statement)) {
            return new MethodDeclarationStatement(statement);
        }
        else if (isCallMethodStatement(statement)) {
            return new CallMethodStatement(statement);
        }
        else if (isExpression(statement)) {
            return new ExpressionStatement(statement);
        }
        else if (isComment(statement)) {
            return new CommentStatement(statement);
        }
        else if (isIncDecStatement(statement)) {
            return new IncDecStatement(statement);
        }
        else if (isBreakStatement(statement)) {
            return new BreakStatement();
        }
        return null;
    }
}
